package com.team.common.result;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@Slf4j
@ControllerAdvice(annotations = {RestController.class, Controller.class})
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> {

    @Autowired
    private GlobalExceptionHandler globalExceptionHandler;

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {

        if(AnnotatedElementUtils.hasAnnotation(methodParameter.getContainingClass(),IgnoreResult.class)
            || methodParameter.hasMethodAnnotation(IgnoreResult.class)){
            return false;
        }
        return AnnotatedElementUtils.hasAnnotation(methodParameter.getContainingClass(),ResponseBody.class)
                || methodParameter.hasMethodAnnotation(ResponseBody.class);
    }

    @Override
    public Object beforeBodyWrite(Object o,
                                  MethodParameter methodParameter,
                                  MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass,
                                  ServerHttpRequest serverHttpRequest,
                                  ServerHttpResponse serverHttpResponse) {
        if(o instanceof Void){
            return o;
        }
        if(o instanceof R){
            return o;
        }
        return R.success(o);
    }

    @ExceptionHandler(Exception.class)
    public R<?> globalExceptionHandler(Exception e){
        return globalExceptionHandler.operationException(e);
    }
}
